/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "client.h"
#include "CoapExchange.h"
#include "ohos_log.h"
#include "Server.h"

EXTERN_C_START
static napi_property_descriptor desc[] = {
    {"setNativeLogOpen", nullptr, OhosLog::SetLogOpen, nullptr, nullptr, nullptr, napi_default, nullptr},
};

static napi_property_descriptor classProp[] = {
    {"request", nullptr, Client::Request, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"setFormat", nullptr, Client::SetFormat, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"setPayload", nullptr, Client::SetPayload, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"setPort", nullptr, Client::SetPort, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"setToken", nullptr, Client::SetToken, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"setWaitSecond", nullptr, Client::SetWaitSecond, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"setObsSecond", nullptr, Client::SetObsSecond, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"setRepeatCount", nullptr, Client::SetRepeatCount, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"addOption", nullptr, Client::AddOption, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"setMid", nullptr, Client::SetMid, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"setPayloadBinary", nullptr, Client::SetPayloadBinary, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"registerOption", nullptr, Client::RegisterOption, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"setBlockMode", nullptr, Client::SetBlockMode, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"setSessionMtu", nullptr, Client::SetSessionMtu, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"setSessionRecvBufferSize", nullptr, Client::SetSessionRecvBufferSize, nullptr, nullptr, nullptr, napi_default, nullptr},
};

static napi_property_descriptor classResourceProp[] = {
    {"addAttributes", nullptr, CoapResource::AddAttributes, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"registerGetHandler", nullptr, CoapResource::RegisterGetHandler, nullptr, nullptr, nullptr, napi_default,
        nullptr},
    {"registerPostHandler", nullptr, CoapResource::RegisterPostHandler, nullptr, nullptr, nullptr, napi_default,
        nullptr},
    {"createResource", nullptr, CoapResource::CreateResource, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"destroy", nullptr, CoapResource::Destroy, nullptr, nullptr, nullptr, napi_default, nullptr},
};

static napi_property_descriptor classServerProp[] = {
    {"start", nullptr, Server::Start, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"stop", nullptr, Server::Stop, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"addResource", nullptr, Server::AddResource, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"setAddr", nullptr, Server::SetAddr, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"getStatus", nullptr, Server::GetStatus, nullptr, nullptr, nullptr, napi_default, nullptr},
};

static napi_property_descriptor classExchangeProp[] = {
    {"response", nullptr, CoapExchange::Response, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"getRequestOptions", nullptr, CoapExchange::GetRequestOptions, nullptr, nullptr, nullptr, napi_default,
        nullptr},
    {"getRequestText", nullptr, CoapExchange::GetRequestText, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"getRequestPayload", nullptr, CoapExchange::GetRequestPayload, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"getSourceAddress", nullptr, CoapExchange::GetSourceAddress, nullptr, nullptr, nullptr, napi_default, nullptr},
};

static napi_value Init(napi_env env, napi_value exports)
{
    OH_LOG_Print(LOG_APP, LOG_ERROR, 0, "libcoap", "VERSION : %{public}s", COAPNAPI_VERSION_STRING);
    napi_value client = nullptr;
    const char *classBindName = "client";
    int methodSize = std::end(classProp) - std::begin(classProp);
    napi_define_class(env, classBindName, strlen(classBindName), Client::JsConstructor, nullptr, methodSize, classProp,
                      &client);
    napi_set_named_property(env, exports, "newCoapClient", client);
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    
    napi_value resource = nullptr;
    const char *classResourceName = "coapResource";
    methodSize = std::end(classResourceProp) - std::begin(classResourceProp);
    napi_define_class(env, classResourceName, strlen(classResourceName), CoapResource::JsConstructor, nullptr,
                      methodSize, classResourceProp, &resource);
    napi_set_named_property(env, exports, "newCoapResource", resource);
    napi_define_properties(env, exports, sizeof(classResourceProp) / sizeof(classResourceProp[0]), classResourceProp);
    
    napi_value server = nullptr;
    const char *classServerName = "server";
    methodSize = std::end(classServerProp) - std::begin(classServerProp);
    napi_define_class(env, classServerName, strlen(classServerName), Server::JsConstructor, nullptr, methodSize,
                      classServerProp, &server);
    napi_set_named_property(env, exports, "newCoapServer", server);
    napi_define_properties(env, exports, sizeof(classServerProp) / sizeof(classServerProp[0]), classServerProp);
    
    napi_value exchange = nullptr;
    const char *classExchangeName = "coapExchange";
    methodSize = std::end(classExchangeProp) - std::begin(classExchangeProp);
    napi_define_class(env, classExchangeName, strlen(classExchangeName), CoapExchange::JsConstructor, nullptr,
                      methodSize, classExchangeProp, &exchange);
    napi_set_named_property(env, exports, "newCoapExchange", exchange);
    napi_define_properties(env, exports, sizeof(classExchangeProp) / sizeof(classExchangeProp[0]), classExchangeProp);
    return exports;
}
EXTERN_C_END

extern "C" void Log_Coap(char *str, int fd) {
    LOGI("coap_io_process %s fd = %d", str, fd);
}

/*
 * Module define
 */
static napi_module coapModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "coap",
    .nm_priv = ((void *)0),
    .reserved = {0},
};

/*
 * Module register function
 */
extern "C" __attribute__((constructor)) void RegisterModule(void)
{
    napi_module_register(&coapModule);
}
